iT邦幫忙

2026 iThome 鐵人賽

DAY 21
0
Software Development

30天打造一套企業PLM系列 第 21

Day 21:壓測與效能調校

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20260907/20161290yBN7brfq01.jpg

系列:30 天打造企業級 PLM|面向:後端|素材:壓測套件(k6 + Node)

問題場景

上線前最怕的一句話:「這系統撐得住全公司同時用嗎?」沒壓測過的答案都是猜的。Mini-PLM 在上線前建了一套可重跑的壓測套件,驗證兩個效能維度:200+ 人併發,以及 BOM 1000+ 筆的大表操作。今天講方法、講發現,也講那兩個被壓測抓出來的秒級熱點怎麼修。

商業邏輯設計

  • 效能目標是業務數字換算出來的。全公司員工數乘上上線時段的併發比例,得到 250 VU。這個數字不是抓整數好看,是從實際人數推的;尖峰在早上第一小時與月底結案潮。
  • 通過門檻先於測試存在:P95 < 2 秒、錯誤率 < 1%。門檻是承諾,測試只是驗收。沒有門檻的壓測只會產生一堆沒有結論的圖。

技術選型與取捨:壓測要壓「真實形狀」的負載

架構演進:從 WebLogic EJB 參數玄學到扁平透明的效能調校

以前在 Oracle Agile PLM 的維運經驗中,效能調校基本上是一門「黑魔法」:

  1. 複雜的 EJB 物件池與快取:管理員要在 WebLogic Console 裡不斷微調 EJB Pool Size、Stateful Session Bean 快取上限、JMS 佇列參數,動一髮牽全局;
  2. 沉重的記憶體與 GC 停頓:EJB 龐大的物件生命週期讓 JVM Heap 動輒需要 16GB 以上,一旦遇到月初簽核高峰,GC Stop-the-World 停頓長達十幾秒,使用者端直接連線逾時;
  3. 黑箱難以定位瓶頸:慢查詢被深埋在 EJB 呼叫鏈下,排查到底卡在 DB 連線池還是 EJB 實例耗盡極為耗時。

Mini-PLM 採用扁平且透明的現代輕量技術棧:沒有 EJB 容器的層層中介,效能核心只看三個關鍵指標——HikariCP 資料庫連線池內嵌 Tomcat 執行緒JPA 批次/原生 SQL,瓶頸在哪裡一清二楚。

單一情境的壓測會騙人,因為真實負載是混合的。套件的組合拳(實際執行流程):

# 1. 建 200 個壓測帳號(SSE 每帳號上限 3 條連線,必須獨立帳號)
node seed-perf-users.mjs --count=200
# 2. 建 BOM 測試資料(60 葉件+12 子組件+3 頂層+1000 筆平面 BOM,共 1510 筆)
node seed-bom-perf.mjs
# 3. 單請求延遲基準(平面 1000 筆讀取、全樹展開、redline 200 筆變更)
node bom-redline-perf.mjs
# 4+5.(同時)監控快照收集 + SSE 長連線 200 人 × 3 條常駐
# 6. k6 混合情境:smoke 驗證 → fast 找斷崖(90s/階,50→250)→ full 撐穩態(4m/階)

這套流程裡有幾個刻意的安排。

  1. SSE 常駐是負載的一部分。600 條長連線掛著再壓 API 流量,長連線吃的連線數與記憶體,單壓 API 永遠測不到(Day 19 的 SSE 在這裡回收)。
  2. 壓測帳號要獨立。SSE 每帳號限 3 條連線,200 VU 共用一個帳號會先撞連線上限,量到的是防護規則的天花板,跟系統效能無關。壓測資料的形狀要跟生產一致,這條踩過才懂。
  3. smoke → fast → full 三段跑:先驗腳本正確,再快速定位斷崖層級,最後長時間撐穩態看資源洩漏。一步到位的大壓測失敗時,你分不出是腳本錯還是系統倒。

核心內容:找斷崖,然後解釋它

「找平均值」的壓測只回答有沒有過門檻;「找斷崖」的壓測回答什麼時候開始壞、誰先倒。階梯式加壓(50→250 VU)盯三個嫌疑人:

  • 連線池(Hikari)。pending 開始持續大於 0,代表 API 在排隊等連線,這通常是第一個倒的。
  • Tomcat 執行緒。執行緒滿載時新請求排隊,P95 階梯式跳升。
  • 快取容量。快取太小換頁頻繁,DB 負載隨 VU 線性上升,這是快取失效的形狀。

結果:250 VU 無斷崖。P95 在門檻內、Hikari pending 恆為 0、heap 不持續攀升。這句話能說出口,靠的是第 4 步的監控快照(pool / SSE / heap / 區間 RPS 與延遲)跟壓測同步收集——沒有監控數據的壓測結論只有「過/不過」,有監控才有「為什麼」。

被抓出來的兩個熱點(與修法)

單請求基準測試(第 3 步)抓出兩個秒級操作:

熱點 原因 修法 出處
BOM 掛載 2.8s 整樹逐筆 ORM 複製 BomBulkCopyDao INSERT-SELECT Day 14
Redline 批次 5.3s 逐筆 save 的 dirty checking saveAll 批次化 Day 15

共同病因是 ORM 逐筆操作被拿去做批次工作。壓測的價值不只在發現慢,更在給出「多慢、慢在哪一步」的數字。沒有 2.8s 這個數字,「BOM 掛載好像有點慢」永遠排不進工作清單。我試過,真的排不進。

踩坑記錄

  • 壓測環境與生產的資料量級差很多。本機 DB 幾千筆料號,生產十幾萬筆,索引失效類的問題本機根本測不出來。緩解方式是關鍵查詢用生產等級的資料量單獨驗,seed 腳本刻意造 1000 筆平面 BOM 就是為此。
  • 寫入型壓測會留垃圾。k6-write 驗證完整寫入生命週期,會留下 PERFW-* 料號與 CANCELLED 表單,所以 README 直接寫明「正式環境禁止執行」。壓測資料要有可辨識前綴,事後才清得掉。
  • 壓測帳號 seed 遇同名多筆直接報錯停止。寧可停下來,也不要在「登入結果不唯一」的狀態下產生無法解讀的數據。

小結

回頭看這套壓測,最值錢的地方是它可以重跑:負載有真實形狀(混合流量加上長連線常駐)、門檻在測試前就定好、斷崖配著監控快照一起看,熱點也因為有了數字才排得進修復清單。上線前的功課做完了,上線後呢?明日 Day 22:監控維運,讓系統自己說話。


上一篇
Day 20:E2E 測試——Playwright 實戰
下一篇
Day 22:監控維運——讓系統自己說話
系列文
30天打造一套企業PLM28
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言